#include "KeyCapturer.h"
#include "DesignModel.h"
#include "ThreadObject.h"
#include "KeyLaunch.h"
#include "DesignBLL.h"

#include <QDebug>
#include <QFile>
#include <QJsonDocument>
#include <QThread>

KeyCapturer::KeyCapturer()
{
    int ret = startHook();
    qInfo() << "startHook ret = " << ret;

    keyLaunch = new KeyLaunch;
}

KeyCapturer::~KeyCapturer()
{
    stopHook();
    delete keyLaunch;
    qInfo() << "stopHook";
}

bool KeyCapturer::hookKeyValue(KBDLLHOOKSTRUCT *key)
{
    // qInfo() << "key->vkCode" << char(key->vkCode) << "key->flags" << key->flags;

    // qInfo() << "==dataLists.count()" << dataLists.count();
    for (int j = 0; j < dataLists.count(); j++)
    {
        QList<QObject *> *dataList = dataLists[j];
        // qInfo() << "dataList.count()" << (*dataList).count();
        for (int i = 0; i < (*dataList).count(); i++)
        {
            DesignModel *model = qobject_cast<DesignModel *>((*dataList)[i]);
            if (model->enable())
            {
                if (model->startKey().count() > 0 && char(key->vkCode) == model->startKey().toUpper().toUtf8().at(0))
                {

                    if (model->keyMode() == 2) // press
                    {
                        if (key->flags == 0) // down
                        {
                            keyUp(getKeyformStr(model->startKey()));
                            return false;
                        }
                        else // up
                        {
                            return true;
                        }
                    }
                    else // ! press
                    {
                        if (key->flags == 0) // down
                        {
                            if (!model->running()) // 未开启线程
                            {
                                // 开启线程
                                qInfo() << char(key->vkCode) << "key start";
                                model->setRunning(true);

                                model->mQThread = new QThread();
                                model->mThreadObject = new ThreadObject((DesignModel *)model);
                                model->mThreadObject->moveToThread(model->mQThread);
                                connect(model->mQThread, &QThread::finished, model->mQThread, &QObject::deleteLater);
                                connect(model->mQThread, &QThread::finished, model->mThreadObject, &QObject::deleteLater);
                                connect(model->mThreadObject, &ThreadObject::sig, model->mThreadObject, &ThreadObject::runKeyLaunchWork);
                                connect(model->mThreadObject, SIGNAL(finished()), model->mQThread, SLOT(quit()));
                                model->mQThread->start();
                                model->mThreadObject->emitsig(); // 主线程通过信号换起子线程的槽函数
                            }
                            else
                            {
                                if (model->keyMode() == 0) // sequence
                                {
                                    // 停止线程
                                    qInfo() << char(key->vkCode) << "key stop";
                                    model->setRunning(false);
                                    if (model->mQThread)
                                    {
                                        if (model->mThreadObject)
                                        {
                                            model->mThreadObject->stop();
                                        }
                                    }
                                }
                            }
                        }
                        if (model->keyMode() == 1) // batter
                        {
                            return false;
                        }
                        return true;
                    }
                }
            }
        }
    }
    return false;
}

void KeyCapturer::addDesignBLL(DesignBLL *designBLL)
{
    designBLLLists.append(designBLL);
    this->dataLists.append(&designBLL->dataList);
}

void KeyCapturer::read(const QJsonObject &json)
{
    if (json.contains("KeyCapturer") && json["KeyCapturer"].isArray())
    {
        for (int i = 0; i < dataLists.count(); ++i)
        {
            QList<QObject *> *dataList = dataLists[i];
            dataList->clear();
        }

        QJsonArray designModelArray = json["KeyCapturer"].toArray();

        for (int i = 0; i < designModelArray.size(); ++i)
        {
            QJsonObject designModelObject = designModelArray[i].toObject();
            DesignModel *designModel = new DesignModel();
            designModel->read(designModelObject);

            designBLLLists[designModel->keyMode()]->monitorDataListChanged(designModel);

            QList<QObject *> *dataList = dataLists[designModel->keyMode()];
            dataList->append(designModel);
        }
    }
}

void KeyCapturer::write(QJsonObject &json) const
{
    QJsonArray designModelArray;

    for (int j = 0; j < dataLists.count(); j++)
    {
        QList<QObject *> *dataList = dataLists[j];
        for (int i = 0; i < (*dataList).count(); i++)
        {
            DesignModel *model = qobject_cast<DesignModel *>((*dataList)[i]);
            QJsonObject designModelObject;
            model->write(designModelObject);
            designModelArray.append(designModelObject);
        }
    }

    json["KeyCapturer"] = designModelArray;
}

bool KeyCapturer::loadKeyCapturer()
{
    QFile loadFile(QStringLiteral("KeyCapturer.json"));

    if (!loadFile.open(QIODevice::ReadOnly))
    {
        qWarning("Couldn't open save file.");
        return false;
    }

    QByteArray saveData = loadFile.readAll();
    QJsonDocument loadDoc(QJsonDocument::fromJson(saveData));
    read(loadDoc.object());

    return true;
}

bool KeyCapturer::saveKeyCapturer() const
{
    QFile saveFile(QStringLiteral("KeyCapturer.json"));

    if (!saveFile.open(QIODevice::WriteOnly))
    {
        qWarning("Couldn't open save file.");
        return false;
    }

    QJsonObject KeyCapturerObject;
    write(KeyCapturerObject);
    QJsonDocument saveDoc(KeyCapturerObject);
    saveFile.write(saveDoc.toJson());

    return true;
}
